/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IMAGE_KNIFE_C_DECODE_INTERCEPTOR_OH_H
#define IMAGE_KNIFE_C_DECODE_INTERCEPTOR_OH_H

#include <multimedia/image_framework/image/image_source_native.h>
#include "interceptor.h"
#include "imageknife_request.h"
#include "imageknife_data_napi.h"

namespace ImageKnifeC {
class DecodeInterceptorOH : public DecodeInterceptor {
public:
    DecodeInterceptorOH()
    {
        name = "Default DecodeInterceptor";
    }

    bool Resolve(std::shared_ptr<ImageKnifeTask> task) override
    {
        if (task->GetImageBufferFormat() == ImageFormat::UNKNOWN) {
            return false;
        }

        if (task->product.imageBuffer != nullptr) {
            bool result = Decode(task->product.imageBuffer.get(), task->product.imageLength, task);
//             task->request->imageKnifeData.timeInfo.decodeEndTime = ImageKnifeDataNapi::GetTimestamp();
            return result;
        }
        return false;
    }
private:
    struct DecodeArgs {
        OH_ImageSourceNative *source = nullptr;
        OH_DecodingOptions *decodeOption = nullptr;
        uint32_t size = 0;

        ~DecodeArgs()
        {
            if (source != nullptr) {
                OH_ImageSourceNative_Release(source);
            }

            if (decodeOption != nullptr) {
                OH_DecodingOptions_Release(decodeOption);
            }
        }
    };

    // TODO 目录获取pixelmap的宽高耦合在拦截器中，后续调整
    bool Decode(uint8_t *buffer, uint32_t length, std::shared_ptr<ImageKnifeTask> task)
    {
        // CreateSource 阶段
//         task->request->imageKnifeData.errorInfo.phase =
//         ImageKnifeDataNapi::phaseToStringMap[LoadPhase::DECODE];
//         task->request->imageKnifeData.timeInfo.decodeStartTime = ImageKnifeDataNapi::GetTimestamp();
        DecodeArgs args;
        Image_ErrorCode imgErrorCode = OH_ImageSourceNative_CreateFromData(buffer, length, &args.source);
        if (imgErrorCode != IMAGE_SUCCESS) {
            task->EchoError("Create ImageSource failed, error code: " + std::to_string(imgErrorCode));
            return false;
        }

        imgErrorCode = OH_ImageSourceNative_GetFrameCount(args.source, &args.size);
        if (imgErrorCode != IMAGE_SUCCESS || args.size < 1) {
//             task->request->imageKnifeData.errorInfo.code = LoadPixelMapCode::IMAGE_SOURCE_ERROR;
            task->EchoError("Get FrameCount Failed, error code: " + std::to_string(imgErrorCode));
            return false;
        }

        // 创建解码Option
        imgErrorCode = OH_DecodingOptions_Create(&args.decodeOption);
        if (imgErrorCode != IMAGE_SUCCESS) {
            task->EchoError("Create Decode Option Failed, error code: " + std::to_string(imgErrorCode));
            return false;
        }

        if (args.size > 1) {
            int *delayList = new int[args.size];
            // 获取每帧时间信息
            imgErrorCode = OH_ImageSourceNative_GetDelayTimeList(args.source, delayList, args.size);
            if (imgErrorCode != IMAGE_SUCCESS) {
                task->EchoError("Create Decode Option Failed, error code: " + std::to_string(imgErrorCode));
                delete [] delayList;
                return false;
            }

            OH_PixelmapNative **pixelmapList = new OH_PixelmapNative* [args.size];
            imgErrorCode = OH_ImageSourceNative_CreatePixelmapList(args.source, args.decodeOption,
                                                                   pixelmapList, args.size);
            if (imgErrorCode != IMAGE_SUCCESS) {
//                 task->request->imageKnifeData.errorInfo.code = LoadPixelMapCode::IMAGE_PIXEL_MAP_ERROR;
                task->EchoError("Create Pixelmap List Failed, error code: " + std::to_string(imgErrorCode));
                delete [] pixelmapList;
                return false;
            }
            task->product.imageData = std::make_shared<ImageData>(pixelmapList, delayList, args.size);
        } else {
            OH_PixelmapNative *pixelmap = nullptr;
            imgErrorCode = OH_ImageSourceNative_CreatePixelmap(args.source, args.decodeOption, &pixelmap);
            if (imgErrorCode != IMAGE_SUCCESS) {
//                 task->request->imageKnifeData.errorInfo.code = LoadPixelMapCode::IMAGE_PIXEL_MAP_ERROR;
                task->EchoError("Create Pixelmap Failed, error code: " + std::to_string(imgErrorCode));
                return false;
            }
            task->product.imageData = std::make_shared<ImageData>(pixelmap);
        }

        return true;
    }
};
};

#endif // IMAGE_KNIFE_C_DECODE_INTERCEPTOR_OH_H
